package com.party.admin.web.controller.coupon;

import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.party.admin.biz.file.ExcelExportService;
import com.party.admin.utils.RealmUtils;
import com.party.admin.utils.excel.ExportExcel;
import com.party.admin.web.dto.AjaxResult;
import com.party.admin.web.dto.input.common.CommonInput;
import com.party.admin.web.dto.output.coupon.CouponCodeExport;
import com.party.common.paging.Page;
import com.party.common.utils.DateUtils;
import com.party.common.utils.LangUtils;
import com.party.common.utils.StringUtils;
import com.party.common.utils.VerifyCodeUtils;
import com.party.core.model.YesNoStatus;
import com.party.core.model.coupon.Coupon;
import com.party.core.model.coupon.CouponCode;
import com.party.core.model.coupon.CouponCodeOutput;
import com.party.core.service.coupon.ICouponCodeService;
import com.party.core.service.coupon.ICouponService;
import com.party.core.service.wallet.biz.WithdrawalsBizService;
import com.party.core.utils.MyBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author：yifeng
 * @description： 核销码控制器
 * @date：Created in  2017/11/28 上午 10:12
 **/
@Controller
@RequestMapping("coupon/couponCode")
public class CouponCodeController {
    @Autowired
    private ICouponService couponService;
    @Autowired
    private ICouponCodeService couponCodeService;
    @Autowired
    private WithdrawalsBizService withdrawalsBizService;
    @Autowired
    private ExcelExportService excelExportService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 核销码列表
     *
     * @param couponCode
     * @param page
     * @return
     */
    @RequestMapping("list")
    public ModelAndView couponCodeList(CouponCode couponCode, Page page, CommonInput commonInput) {
        page.setLimit(20);
        if (StringUtils.isNotEmpty(couponCode.getVerifyCode())) {
            couponCode.setVerifyCode(couponCode.getVerifyCode().replace(" ", ""));
        }
        Map<String, Object> params = CommonInput.appendParams(commonInput);
        List<CouponCodeOutput> couponCodes = couponCodeService.webListPage(couponCode, params, page);
        for (CouponCodeOutput codeOutput : couponCodes) {
            String accountNumber = withdrawalsBizService.formatAccountNumber(codeOutput.getVerifyCode());
            codeOutput.setVerifyCode(accountNumber);
        }
        ModelAndView mv = new ModelAndView("coupon/couponCodeList");
        mv.addObject("couponCodes", couponCodes);
        mv.addObject("page", page);
        Coupon coupon = couponService.get(couponCode.getCouponId());
        mv.addObject("coupon", coupon);
        mv.addObject("couponCode", couponCode);
        mv.addObject("input", commonInput);
        return mv;
    }

    /**
     * 新增/编辑
     *
     * @param couponId 券id
     * @param codeId   码id
     * @return
     */
    @RequestMapping("toForm")
    public ModelAndView toForm(String couponId, String codeId) {
        ModelAndView mv = new ModelAndView("coupon/couponCodeForm");
        Coupon coupon = couponService.get(couponId);
        if (StringUtils.isNotEmpty(couponId)) {
            CouponCode couponCode = couponCodeService.get(codeId);
            mv.addObject("couponCode", couponCode);
        }
        mv.addObject("coupon", coupon);
        return mv;
    }

    /**
     * 保存核销码
     *
     * @param couponCode
     * @return
     */
    @ResponseBody
    @RequestMapping("save")
    public AjaxResult save(CouponCode couponCode) {
        try {
            String memberId = RealmUtils.getCurrentUser().getId();
            couponCode.setUpdateBy(memberId);
            if (StringUtils.isNotEmpty(couponCode.getVerifyCode())) {
                couponCode.setVerifyCode(couponCode.getVerifyCode().replace(" ", ""));
            }
            if (StringUtils.isEmpty(couponCode.getId())) {
                couponCodeService.insert(couponCode);

                Coupon coupon = couponService.get(couponCode.getCouponId());
                if (coupon.getStock() == null) {
                    coupon.setStock(1L);
                } else {
                    coupon.setStock(coupon.getStock() + 1);
                }
                couponService.update(coupon);
            } else {
                couponCodeService.update(couponCode);
            }
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("保存核销码异常", e);
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 删除核销码
     *
     * @param codeId
     * @return
     */
    @ResponseBody
    @RequestMapping("delete")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public AjaxResult delete(String codeId) {
        if (StringUtils.isEmpty(codeId)) {
            return AjaxResult.error("id不能为空");
        }
        try {
            CouponCode couponCode = couponCodeService.get(codeId);
            if (YesNoStatus.YES.getCode().equals(couponCode.getIsUsed())) {
                return AjaxResult.error("该码已有人领取，不能删除");
            }
            // 没有用户领取，可以删除
            couponCodeService.delete(codeId);
            Coupon coupon = couponService.get(couponCode.getCouponId());
            if (coupon.getStock() == null || coupon.getStock() < 0) {
                coupon.setStock(0L);
            } else {
                coupon.setStock(coupon.getStock() - 1);
            }
            couponService.update(coupon);
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("删除核销码异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("删除失败");
        }
    }

    /**
     * 检查核销码唯一性
     *
     * @param couponCode
     * @return
     */
    @ResponseBody
    @RequestMapping("checkVerifyCode")
    public Boolean checkVerifyCode(CouponCode couponCode) {
        CouponCode query = new CouponCode();
        query.setVerifyCode(couponCode.getVerifyCode());
        List<CouponCode> codes = couponCodeService.list(query);
        if (StringUtils.isEmpty(couponCode.getId())) {
            if (codes.size() > 0) {
                return false;
            }
        } else {
            for (CouponCode code : codes) {
                if (!code.getId().equals(couponCode.getId())) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 批量生成核销码
     *
     * @param couponId 券id
     * @param count    数量
     * @return
     */
    @ResponseBody
    @RequestMapping("randomInsert")
    public AjaxResult randomInsert(String couponId, int count) {
        String memberId = RealmUtils.getCurrentUser().getId();
        for (int i = 0; i < count; i++) {
            synchronized (this) {
                String verifyCode = DateUtils.formatDate(new Date(), DateUtils.DATE_SHORT_PATTERN) + VerifyCodeUtils.RandomNumber(8);
                CouponCode couponCode = couponCodeService.getUnique(new CouponCode(verifyCode, couponId));
                if (couponCode == null) {
                    couponCode = new CouponCode();
                    couponCode.setUpdateBy(memberId);
                    couponCode.setCouponId(couponId);
                    couponCode.setVerifyCode(verifyCode);
                    couponCodeService.insert(couponCode);
                }
            }
        }
        Coupon coupon = couponService.get(couponId);
        Long total = couponCodeService.getCountByCoupon(couponId);
        coupon.setStock(total);
        couponService.update(coupon);
        return AjaxResult.success();
    }

    /**
     * 核销码导出
     *
     * @param couponCode
     * @param commonInput
     * @return
     */
    @ResponseBody
    @RequestMapping("exportCouponCode")
    public AjaxResult exportCouponCode(CouponCode couponCode, CommonInput commonInput) {
        try {
            if (StringUtils.isNotEmpty(couponCode.getVerifyCode())) {
                couponCode.setVerifyCode(couponCode.getVerifyCode().replace(" ", ""));
            }
            Map<String, Object> params = CommonInput.appendParams(commonInput);
            List<CouponCodeOutput> couponCodes = couponCodeService.webListPage(couponCode, params, null);
            List<CouponCodeExport> couponCodeExports = LangUtils.transform(couponCodes, new Function<CouponCodeOutput, CouponCodeExport>() {
                @Override
                public CouponCodeExport apply(CouponCodeOutput input) {
                    CouponCodeExport output = new CouponCodeExport();
                    try {
                        MyBeanUtils.copyBeanNotNull2Bean(input, output);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    String accountNumber = withdrawalsBizService.formatAccountNumber(input.getVerifyCode());
                    output.setVerifyCode(accountNumber);

                    if (input.getIsUsed() == 1) output.setIsUsed("已使用");
                    if (input.getIsUsed() == 2) output.setIsUsed("未使用");
                    if (input.getIsSpending() == 1) output.setIsSpending("已消费");
                    if (input.getIsSpending() == 2) output.setIsSpending("未消费");
                    return output;
                }
            });
            Coupon coupon = couponService.get(couponCode.getCouponId());
            String fileName = coupon.getName() + "的核销码.xlsx";
            ExportExcel exportExcel = new ExportExcel("", CouponCodeExport.class).setDataList(couponCodeExports);
            String allPath = excelExportService.getExcelPath(fileName, "coupon", exportExcel);
            return AjaxResult.success((Object) allPath);
        } catch (Exception e) {
            logger.error("核销码导出异常");
            return AjaxResult.error("导出失败");
        }
    }

    @ResponseBody
    @RequestMapping("batchVerify")
    public AjaxResult batchVerify(String verifyCodes, String couponId) {
        try {
            if (StringUtils.isEmpty(verifyCodes)) {
                return AjaxResult.error("核销不能为空");
            }
            if (StringUtils.isEmpty(couponId)) {
                return AjaxResult.error("票券id不能为空");
            }
            String[] verifyCodeArray = verifyCodes.split(",");
            Map<String, String> errorCode = Maps.newHashMap();
            for (String verifyCode : verifyCodeArray) {
                verifyCode = verifyCode.replaceAll(" ", "");
                try {
                    CouponCode couponCode = couponCodeService.getUnique(new CouponCode(verifyCode, couponId));
                    if (null != couponCode) {
                        if (YesNoStatus.YES.getCode().equals(couponCode.getIsUsed())) {
                            if (!YesNoStatus.YES.getCode().equals(couponCode.getIsSpending())) {
                                couponCode.setIsSpending(YesNoStatus.YES.getCode());
                                couponCode.setSpendingTime(new Date());
                                couponCodeService.update(couponCode);
                            } else {
                                errorCode.put(verifyCode, "该核销码已核销");
                            }
                        } else {
                            errorCode.put(verifyCode, "该核销码还未领取");
                        }
                    } else {
                        errorCode.put(verifyCode, "该核销码不存在");
                    }
                } catch (Exception e) {
                    logger.error("核销异常", e);
                    errorCode.put(verifyCode, "该核销码异常");
                    continue;
                }
            }
            if (errorCode.size() > 0) {
                return AjaxResult.error("核销失败的有这些：<br/>", errorCode);
            }
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("核销异常", e);
            return AjaxResult.error("核销失败");
        }
    }
}
